﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Calculator;
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;

namespace CalculatorTest
{
    partial class MainPage
    {
        public MainPage()
        {
            InitializeComponent();

            CalculatorEngineTest test = new CalculatorEngineTest();
            try
            {
                test.TestInitialize(); test.TestAdd();
                test.TestInitialize(); test.TestSubtract();
                test.TestInitialize(); test.TestMultiply();
                test.TestInitialize(); test.TestDivide();
                test.TestInitialize(); test.TestDecimals();
                test.TestInitialize(); test.TestAddAdd();
                test.TestInitialize(); test.TestAddAuto();
                test.TestInitialize(); test.TestAddEqualsAdd();
                test.TestInitialize(); test.TestNegatePos();
                test.TestInitialize(); test.TestNegateNeg();
                test.TestInitialize(); test.TestNegateLastValue();
                test.TestInitialize(); test.TestClear();
                test.TestInitialize(); test.TestClearEmpty();
                test.TestInitialize(); test.TestClearEverything();
                test.TestInitialize(); test.TestClearWithSomethingInLast();
                test.TestInitialize(); test.TestReciprical();
                test.TestInitialize(); test.TestBackspaceEmpty();
                test.TestInitialize(); test.TestBackspaceWithNumbers();
                test.TestInitialize(); test.TestDecimalWithEmptyCurrent();
                _error.Text = "Success";
            }
            catch (Exception ex)
            {
                _error.Text = ex.ToString();
            }
        }
    }

    public class CalculatorEngineTest
    {
        private CalculatorEngine _engine;

        public void TestInitialize()
        {
            _engine = new CalculatorEngine();
        }

        public void TestAdd()
        {
            _engine.ProcessKey("1");
            _engine.ProcessKey("+");
            _engine.ProcessKey("2");
            _engine.ProcessKey("=");
            Assert.AreEqual("3", _engine.CurrentValue);
        }

        public void TestAddAuto()
        {
            _engine.ProcessKey("1");
            _engine.ProcessKey("+");
            _engine.ProcessKey("2");
            _engine.ProcessKey("+");
            Assert.AreEqual("3", _engine.CurrentValue);
        }

        public void TestAddEqualsAdd()
        {
            _engine.ProcessKey("1");
            _engine.ProcessKey("+");
            _engine.ProcessKey("2");
            _engine.ProcessKey("=");
            _engine.ProcessKey("+");
            _engine.ProcessKey("3");
            _engine.ProcessKey("=");
            Assert.AreEqual("6", _engine.CurrentValue);
        }

        public void TestAddAdd()
        {
            _engine.ProcessKey("1");
            _engine.ProcessKey("+");
            _engine.ProcessKey("2");
            _engine.ProcessKey("+");
            _engine.ProcessKey("3");
            _engine.ProcessKey("=");
            Assert.AreEqual("6", _engine.CurrentValue);
        }

        public void TestNegatePos()
        {
            _engine.CurrentValue = "1";
            _engine.ProcessKey("+/-");
            Assert.AreEqual("-1", _engine.CurrentValue);
        }

        public void TestNegateNeg()
        {
            _engine.CurrentValue = "-1";
            _engine.ProcessKey("+/-");
            Assert.AreEqual("1", _engine.CurrentValue);
        }

        public void TestNegateLastValue()
        {
            _engine.CurrentValue = "-1";
            _engine.ProcessKey("+");
            _engine.ProcessKey("+/-");
            Assert.AreEqual("1", _engine.CurrentValue);
        }

        public void TestClear()
        {
            _engine.ProcessKey("1");
            _engine.ProcessKey("+");
            _engine.ProcessKey("2");
            _engine.ProcessKey("C");
            Assert.AreEqual("1", _engine.CurrentValue);
            _engine.ProcessKey("3");
            Assert.AreEqual("3", _engine.CurrentValue);
        }

        public void TestClearEmpty()
        {
            _engine.ProcessKey("C");
            Assert.AreEqual("0", _engine.CurrentValue);
            _engine.ProcessKey("3");
            Assert.AreEqual("3", _engine.CurrentValue);
        }

        public void TestClearWithSomethingInLast()
        {
            _engine.ProcessKey("1");
            _engine.ProcessKey("+");
            _engine.ProcessKey("2");
            _engine.ProcessKey("=");
            Assert.AreEqual("3", _engine.CurrentValue);
            _engine.ProcessKey("C");
            Assert.AreEqual("0", _engine.CurrentValue);
            _engine.ProcessKey("2");
            Assert.AreEqual("2", _engine.CurrentValue);
        }

        public void TestClearEverything()
        {
            _engine.ProcessKey("1");
            _engine.ProcessKey("+");
            _engine.ProcessKey("2");
            _engine.ProcessKey("CE");
            Assert.AreEqual("0", _engine.CurrentValue);
            _engine.ProcessKey("3");
            Assert.AreEqual("3", _engine.CurrentValue);
        }

        public void TestSubtract()
        {
            _engine.ProcessKey("1");
            _engine.ProcessKey("-");
            _engine.ProcessKey("2");
            _engine.ProcessKey("=");
            Assert.AreEqual("-1", _engine.CurrentValue);
        }

        public void TestMultiply()
        {
            _engine.ProcessKey("2");
            _engine.ProcessKey("*");
            _engine.ProcessKey("3");
            _engine.ProcessKey("=");
            Assert.AreEqual("6", _engine.CurrentValue);
        }

        public void TestDivide()
        {
            _engine.ProcessKey("1");
            _engine.ProcessKey("/");
            _engine.ProcessKey("2");
            _engine.ProcessKey("=");
            Assert.AreEqual("0.5", _engine.CurrentValue);
        }

        public void TestDecimals()
        {
            _engine.ProcessKey("1"); // 1.2
            _engine.ProcessKey(".");
            _engine.ProcessKey("2");
            _engine.ProcessKey("+");
            _engine.ProcessKey("1"); // 13.4
            _engine.ProcessKey("3");
            _engine.ProcessKey(".");
            _engine.ProcessKey("4");
            _engine.ProcessKey("=");
            Assert.AreEqual("14.6", _engine.CurrentValue);
        }

        public void TestReciprical()
        {
            _engine.ProcessKey("2");
            _engine.ProcessKey("1/x");
            Assert.AreEqual("0.5", _engine.CurrentValue);
        }

        public void TestBackspaceEmpty()
        {
            try
            {
                _engine.ProcessKey("<-");
                Assert.Fail("exception expected");
            }
            catch (Exception ex)
            {
                // good
            }
        }

        public void TestBackspaceWithNumbers()
        {
            _engine.ProcessKey("1");
            _engine.ProcessKey("2");
            _engine.ProcessKey("<-");
            Assert.AreEqual("1", _engine.CurrentValue);
        }

        public void TestDecimalWithEmptyCurrent()
        {
            _engine.ProcessKey(".");
            Assert.AreEqual("0.", _engine.CurrentValue);
            _engine.ProcessKey("1");
            Assert.AreEqual("0.1", _engine.CurrentValue);
        }
    }
}
